package com.bingbaihanji.core.config.security.jwt;

import com.bingbaihanji.core.service.impl.MyUserDetailServiceImpl;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * JWT 认证过滤器，用于处理每个请求中的 JWT 认证逻辑。
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

    @Autowired
    private MyUserDetailServiceImpl userDetailsService;  // 用户详细信息服务

    @Autowired
    private JwtTokenUtil jwtTokenUtil;  // JWT 令牌工具类

    @Autowired
    private JwtProperties jwtProperties;  // JWT 配置属性

    /**
     * 默认构造函数
     */
    public JwtAuthenticationTokenFilter() {
    }

    /**
     * 处理每个请求，检查并验证 JWT 令牌。
     *
     * @param httpServletRequest  请求对象
     * @param httpServletResponse 响应对象
     * @param filterChain         过滤器链
     * @throws ServletException  处理请求时可能抛出的异常
     * @throws IOException       处理请求时可能抛出的异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        // 从请求头中获取 JWT 令牌
        String authToken = httpServletRequest.getHeader(jwtProperties.getHeader());

        // 从 JWT 令牌中提取用户名
        String username = jwtTokenUtil.getUsernameFromToken(authToken);

        log.info("进入自定义过滤器");
        log.info("自定义过滤器获得用户名为 {}", username);

        // 如果用户名不为空且当前上下文中没有认证信息，则进行认证
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            // 根据用户名加载用户详细信息
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            // 验证 JWT 令牌的有效性
            if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                // 创建认证对象
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                // 设置认证详情
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));

                // 将认证信息放入 SecurityContextHolder 中
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        // 继续过滤链
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}
